/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package CA;

import Utility.*;
import Utility.exceptions.ExceptionCertificatoGiaPresente;
import Utility.exceptions.ExceptionCertificatoNonCreato;
import Utility.exceptions.ExceptionCertificatoNonValido;
import Utility.exceptions.ExceptionFirmaNonCorretta;
import Utility.exceptions.ExceptionProfiloGiaPresente;
import Utility.exceptions.ExceptionRichiestaDiCertificatoGiaPresente;
import java.io.*;
import java.math.BigInteger;
import java.security.*;
import java.security.cert.*;
import java.util.Calendar;
import java.util.Date;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.x500.X500Principal;
import javax.xml.transform.TransformerException;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.server.PropertyHandlerMapping;
import org.apache.xmlrpc.server.XmlRpcServer;
import org.apache.xmlrpc.server.XmlRpcServerConfigImpl;
import org.apache.xmlrpc.webserver.WebServer;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.pkcs.Attribute;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x509.CRLNumber;
import org.bouncycastle.asn1.x509.CRLReason;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.X509Extensions;
import org.bouncycastle.jce.PKCS10CertificationRequest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.ocsp.*;
import org.bouncycastle.openssl.PEMReader;
import org.bouncycastle.openssl.PEMWriter;
import org.bouncycastle.openssl.PasswordFinder;
import org.bouncycastle.util.encoders.Base64;
import org.bouncycastle.x509.X509V2CRLGenerator;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import org.bouncycastle.x509.extension.AuthorityKeyIdentifierStructure;
import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure;
import org.w3c.dom.Document;
/**
 *
 * @author 
 */

public final class Ca extends WebServer
{   
    /*
     * Coppia di chiavi RSA
     */
    private KeyPair kp = null;
    private PublicKey pubKey = null;
    private PrivateKey privKey = null;
        
    String password = "BiancaNe7=Nani";
    X509Certificate caCert = null;
    KeyStore ks = null; // per salvare i certificati
    X509CRL Crl = null; // CRL
    
    int politica=Utility.POLITICA_CRL_RIGENERAZIONE_OGNI_RICHIESTA;
    
    /*
     * Handler per l'invocazione remota
     */
    private String handler = "ServiziCA";
    
    /*
     * Ultima modifica
     */
    Date last_call = Calendar.getInstance().getTime(); 
    String message_gui = "Server inizializzato e pronto per ricevere richieste";
    
    // durata certificati
    int durata = 5;
    //int durata = 0;
    
    /**
     * Costruttore
     * @param porta : porta di ascolto
     * @throws KeyStoreException
     * @throws CertificateException
     * @throws IOException
     * @throws Exception
     * @throws NoSuchProviderException
     * @throws SecurityException
     * @throws SignatureException 
     */
    public Ca(int porta) throws KeyStoreException, CertificateException, IOException, Exception, NoSuchProviderException, SecurityException, SignatureException{
            
        /*
         * Creo il webserver CA e devo settare la porta
         */
        super(porta);
           
        /*
         * Se la CA è avviata per la prima volta genera il certificato e la coppia di chiavi
         */
        System.out.println("\n-----------------\n"
                + "AVVIO DELLA CA");
        if(!(new File("ca")).exists()) 
        {
            System.out.print("PRIMO AVVIO DELLA CA");
            
            /*
             * Creo directory per i file creati e per il database
             */
            boolean directoryCa = new File("ca").mkdir();
           
            /*
             * Creo la directory per il database SQLite e inizializzo il database
             */
            GestioneSQLite.inizializzaDb();
                        
            if(directoryCa && (new File("ca/key").mkdir()) && new File("ca/cert").mkdir())
            {
                try {
                    this.creaCertificatoCA();

                } catch (IOException ex) {
                    Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
                } catch (CertificateEncodingException ex) {
                    Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalStateException ex) {
                    Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
                } catch (NoSuchProviderException ex) {
                    Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
                } catch (NoSuchAlgorithmException ex) {
                    Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
                } catch (SignatureException ex) {
                    Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
                } catch (InvalidKeyException ex) {
                    Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        }else{
            /*
             * Esistono già il certificato e le chiavi pubbliche
             * Non mi resta che caricare i dati esistenti
             */
            // legge i dati della ca già esistenti
            System.out.println("CARICO I DATI DELLA CA");
            this.readKey();
            this.readCert(); 
            
            // Se il certificato della CA è scaduto (5 anni) lo ricreo
            try{this.caCert.checkValidity();}
            catch(Exception e){
                this.creaCertificatoCA();
            }
                          
            System.out.println("CARICO LA CRL");
            this.createCRL();
            
            System.out.println("DATI CA CARICATI");
        }
            
        //inizializzo comunicazione XMLRPC
        System.out.println("INIZIALIZZO SERVER");

        XmlRpcServer xmlRpcServer = this.getXmlRpcServer();
        PropertyHandlerMapping phm = new PropertyHandlerMapping();
        phm.setRequestProcessorFactoryFactory(new EchoRequestProcessorFactoryCA(this));
        phm.setVoidMethodEnabled(true);
        System.out.println("NOME HANDLER: "+handler);
        phm.addHandler(handler, Ca.class);
        xmlRpcServer.setHandlerMapping(phm);
        XmlRpcServerConfigImpl serverConfig = (XmlRpcServerConfigImpl) xmlRpcServer.getConfig();
        serverConfig.setEnabledForExtensions(true);
        serverConfig.setContentLengthOptional(false);

        System.out.println("SERVER INIZIALIZZATO");
        System.out.println("--------------------\n");            
    }
    //fine costruttore
    

    /*
     * Funzione che salva nel database della CA la richiesta PKCS10 del client
     * per avere un certificato
     * In input riceve il Document firmato nel Digital Signature: devo verificare la firma
     * - Ritorna 1 se e' andato tutto a buon fine, altrimenti 0
     * - Ritorna 2 se è presente in coda una richiesta uguale --- NON LA FA!
     * - Ritorna 3 se la validazione del digital signature ha esito negativo
     * 
     * Il risultato di status viene ritornato in un documento firmato
     * <risultato>
     *  <status>xxx</status>
     * </risultato>
     */
    /**
     *
     * @param doc_digsign
     * @return
     */
    public Document richiediCertificato(Document doc_digsign){
        
        System.out.println("\n---------------------");
        System.out.println("RICEVUTA RICHIESTA DI CERTIFICATO");
                
        // valore che verrà inserito nel documento di ritorno
        int status_integer = 0;                
        
        // client che ha chiamato la CA
        String username = null;        
  
            /*
             * Devo verificare che il digital signature sia corretto
            * Validazione del digital signature errata di default
            * status = 3
            * !ValidateXMLSig.validateDigitalSignature(doc_digsign    
            */               
            if(validaXml(doc_digsign)==0){
                status_integer = 3;
                System.out.println("RICHIESTA DI CERTIFICATO NON VALIDA");
            }else{
            try {
                /*
                * Inserisco la richiesta pkcs10 nel database
                * Resterà in attesa di conferma da parte della CA
                * La CA confermerà e creerà il certificato che verrà salvato nel databse
                * Il client potrà poi richiedere il certificato
                */                
                
                String pkcs = XMLUtility.getValueStringInXML(doc_digsign, "pkcs10");
                username = XMLUtility.getValueStringInXML(doc_digsign, "id");
                String tipo = XMLUtility.getValueStringInXML(doc_digsign, "tipo");             
                
                String nome = XMLUtility.getValueStringInXML(doc_digsign, "nome");
                String cognome = XMLUtility.getValueStringInXML(doc_digsign, "cognome");
                String organizzazione = XMLUtility.getValueStringInXML(doc_digsign, "organizzazione");
                String unita = XMLUtility.getValueStringInXML(doc_digsign, "unita");
                String paese = XMLUtility.getValueStringInXML(doc_digsign, "paese");
                String email = XMLUtility.getValueStringInXML(doc_digsign, "email");
    
                if(!GestioneSQLite.inserisciProfilo(nome, cognome, organizzazione, unita, paese, email)){
                    System.out.println("UTENTE GIÀ PRESENTE NEL DB");
                }
                
                boolean status = GestioneSQLite.inserisciRichiestaPKCS10(pkcs, username, tipo, Utility.NUOVO_CERTIFICATO );
    
                if (status) {
                    status_integer = 1;
                }

                System.out.println("RICHIESTA INSERITA NEL DB");
                System.out.println("Richiesta inserita in SQLite");
                last_call = Calendar.getInstance().getTime();
                message_gui = "Ricevuta richiesta di certificato da "+username;
            } catch (ExceptionRichiestaDiCertificatoGiaPresente ex) {
                System.out.println("RICHIESTA DI CERTIFICATO GIÀ PRESENTE");
            } catch (ExceptionProfiloGiaPresente ex) {
                System.out.println("PROFILO GIÀ ESISTENTE");
            }
        }
                
        // Creao il documento con la risposta
        System.out.println("CREO LA RISPOSTA XML PER IL CLIENT "+ username);                
        Document status_doc = XMLUtility.getDocumentRispostaInt(status_integer);
        
        // Firmo il documento
        System.out.println("FIRMO LA RISPOSTA XML PER CLIENT");                
        Document status_doc_sign = XMLUtility.firmaDocumento(status_doc, privKey, pubKey);        
        
        System.out.println("RICHIESTA TERMINATA");                
        System.out.println("---------------------\n");        
        
        return status_doc_sign;
        
    }
    
  /**
   * Richiedi il rinnovo di Certificato
   * @param tipo
   * @param pair
   * @param username
   * @return
   * @throws XmlRpcException
   * @throws Exception 
   */
  private boolean richiediRinnovoCertificato(String tipo, String pair, String nome, String cognome, int rinnovo){
        try {
            System.out.println("\nINVIO RICHIESTA DI CERTIFICATO ");

            // nel caso sia un rinnovo, devo verificare che sia presente un certificato rinnovabile
            if(rinnovo==Utility.RINNOVO_CERTIFICATO){
                String val= GestioneSQLite.getCertRinnovabile(nome +" "+cognome, tipo);
                if(val==null || val.equals("") || val.isEmpty()){
                    return false;
                } 
            }
            // carico info utente
            Profilo profilo = GestioneSQLite.getProfilo(nome,cognome);
            
            System.out.println("PROFILO DI "+cognome+" TROVATO "+profilo.getNome());            
            
            String CN = profilo.getNome()+" "+profilo.getCognome();
            String O = profilo.getOrganizzazione();
            String OU = profilo.getUnita();
            String C = profilo.getPaese();
            String email = profilo.getEmail();
            
            StringReader pubblicaSW = new StringReader(pair);
            PEMReader pubblicaPW = new PEMReader(pubblicaSW);
            KeyPair pairKey = (KeyPair) pubblicaPW.readObject();        

            System.out.println("CARICATE INFORMAZIONI UTENTE");        

            GeneralNames subjectAltName = new GeneralNames(new GeneralName(GeneralName.rfc822Name, email));                        
            Vector oids = new Vector(); 
            Vector values = new Vector(); 
            oids.add(X509Extensions.SubjectAlternativeName); 
            values.add(new org.bouncycastle.asn1.x509.X509Extension(false, new DEROctetString(subjectAltName))); 

            // impostazione uso chiave 
            KeyUsage k = new KeyUsage(0); 
            oids.add(X509Extensions.KeyUsage); 
            values.add(new org.bouncycastle.asn1.x509.X509Extension(true, new DEROctetString(k))); 
            X509Extensions extensions = new X509Extensions(oids, values); 
            Attribute attribute = new Attribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest,new DERSet(extensions)); 
            PKCS10CertificationRequest pkcs10req = new PKCS10CertificationRequest("SHA256WithRSAEncryption", 
            new X500Principal("CN=" + CN + ", O=" + O + ", OU=" + OU 
            + ", C=" + C), (PublicKey)pairKey.getPublic(), new DERSet( 
            attribute), (PrivateKey) pairKey.getPrivate()); 
            // Creata la richiesta PKCS10

            // USARE FIRMA DI UTILITY XML
            System.out.println("CREO XML CON PARAMETRI DA INVIARE");
            byte[] coded = Base64.encode(pkcs10req.getEncoded());
            String strCoded = new String(coded);                  

            System.out.println("INSERISCO RICHIESTA PKCS10 PER IL RINNOVO NEL DATABASE");
            return GestioneSQLite.inserisciRichiestaPKCS10(strCoded, nome +" "+cognome, tipo, rinnovo);
        } catch (ExceptionRichiestaDiCertificatoGiaPresente ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchProviderException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidKeyException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SignatureException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        }
        return false;

     
    }    
   
    /**
     * Crea un certificato dalla richiesta PKCS10
     * E' chiamata dalla CA
     * - PKCS10 generato dal client
     * - Username client
     * - Tipo: certificato di crittografia (codifica) e di firma 
     * @param pkcs
     * @param username
     * @param tipo
     * @param rinnovo
     * @return 
     */
    public boolean creaX509FromPKCS10(String pkcs, String username, String tipo, String rinnovo)
    {
        System.out.println("\n---------------------"); 
        
            // questo metodo sara invocato dalla gui per la creazione di un certificato
            // quando ne recuperera dalla lista
            
            System.out.println("CREO CERTIFICATO DA PKCS10"); 
            try 
            {
                byte[] decoded = Base64.decode(pkcs);
                PKCS10CertificationRequest pkcs10 = new PKCS10CertificationRequest(decoded);            
                X509Certificate rootCert = caCert;
                X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
                X500Principal subjectName = new X500Principal(pkcs10.getCertificationRequestInfo().getSubject().toString());
                certGen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
                certGen.setIssuerDN(rootCert.getSubjectX500Principal());

                // Data di creazione
                Calendar ora = Calendar.getInstance();
                Date now = ora.getTime();
                // Data di scadenza 5 anni dalla creazione
                int year_futuro = ora.get(Calendar.YEAR)+durata;                
                Calendar calendar_futuro = Calendar.getInstance();               
                calendar_futuro.set(Calendar.YEAR, (year_futuro));
                Date data_futuro = calendar_futuro.getTime();  

                certGen.setNotBefore(now);
                certGen.setNotAfter(data_futuro);
                certGen.setSubjectDN(subjectName);
                certGen.setPublicKey(pkcs10.getPublicKey());
                certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
                certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,new AuthorityKeyIdentifierStructure(rootCert));
                certGen.addExtension(X509Extensions.SubjectKeyIdentifier, false,new SubjectKeyIdentifierStructure(pkcs10.getPublicKey()));
                X509Certificate cert = certGen.generate((PrivateKey) getPrivKey(), "BC");   // note: private key of CA

                /*
                    * Inserisco il certificato nel database
                    * Ma se il certificato è già presente allora viene lanciata l'eccezione
                    * ExceptionCertificatoGiaPresente
                    */
                byte[] certCoded = Base64.encode(cert.getEncoded());
                String strCertCoded = new String(certCoded);                  
                        
                if(Integer.parseInt(rinnovo)==Utility.NUOVO_CERTIFICATO){
                    GestioneSQLite.inserisciCertFirma(strCertCoded, username, tipo, cert.getSerialNumber().toString(), Utility.convertDateToString(now), Utility.convertDateToString(data_futuro));
                }else{
                    System.out.println("ACCETTO RICHIESTA DI RINNOVO");
                    System.out.println("RECUPERO IL CERTIFICATO DEL CLIENT "+username+" tipo: "+tipo);
                    String certificato_client_string = GestioneSQLite.getCertFirma(username, tipo);
                    System.out.println("CREO IL CERTIFICATO DAL PARAMETRO");                                       
                    X509Certificate cert509 = Utility.creaCertificatoDaStringa(certificato_client_string);                    
                    System.out.println("CONVERTO IN STRINGA IL VECCHIO CERTIFICATO");
                    String certificato_vecchio_string = Utility.creaStringaDaCertificato(cert509); 
                    
                    System.out.println("RECUPERO SERIAL NUMBER NUOVO CERTIFICATO");
                    BigInteger serial = cert.getSerialNumber(); 
                    String serial_string = serial.toString();
        
                    System.out.println("INSERISCO NUOVO CERTIFICATO RINNOVATO MODIFICANDO IL VECCHIO");
                    GestioneSQLite.rinnovoCertificato(strCertCoded, username, Utility.convertDateToString(now), Utility.convertDateToString(data_futuro), tipo, certificato_vecchio_string, serial_string); 
                }
                
                last_call = Calendar.getInstance().getTime();  
                this.message_gui = "Qualcuno ha ottenuto il certificato di "+username;
                return true;

        } catch (ExceptionCertificatoNonCreato ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ExceptionCertificatoGiaPresente ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CertificateEncodingException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalStateException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SignatureException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CertificateParsingException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchProviderException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidKeyException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        }

        System.out.println("---------------------\n");         
        last_call = Calendar.getInstance().getTime();
        this.message_gui = "Non è stato restituito il certificato di "+username;
        return false;
    }
    
    /*
     * Funzione che mi ritorna se esiste nella lista dei certificati il certificato di
     * - username
     * - tipo
     * I parametri vengono inviati via document xml firmato
     * Quindi viene verificata la firma e vengono estratti i dati
     */
    /**
     *
     * @param docxml
     * @return
     * @throws ExceptionFirmaNonCorretta
     */
    public Document getCertStatusByUsername(Document  docxml) throws ExceptionFirmaNonCorretta{

        // di default 0 -> non esiste il certificato
        int status = 0;
        
        // controllo se il documento è firmato correttamente
        if(!(validaXml(docxml)!=0)){           
            throw new ExceptionFirmaNonCorretta();
        }
                
        String username = XMLUtility.getValueStringInXML(docxml, "id");        
        String tipo = XMLUtility.getValueStringInXML(docxml, "tipo");
        
        // Recupero il certificato
        String val = GestioneSQLite.getCertFirma(username, tipo);
        
        if(!val.equals("") && val!=null  && !val.isEmpty()) {
            status = 1;
        }   // -> il certificato esiste
        
        System.out.println("Il certificato di "+username+ " è: "+val);

        // Creo il file xml che contiene i parametri: status. Il file xml mi serve per firmarlo nel digsign
        Document statusXML = XMLUtility.getDocumentStatus(Integer.toString(status));
        
        // Firmo il documento
        statusXML = XMLUtility.firmaDocumento(statusXML, this.getPrivKey(), this.getPubKey());                     
        
        return statusXML;

    }
    
    
    
    /**
     * Funzione che valida il documento xml inviato da un client, se possibile
     * return:  0 se la validazione fallisce
     *          1 se la validazione è passata, utilizzando il certificato del client
     *          2 se la validazione è passata, ma basandosi sulla chiave pubblica 
     *              inserita nel doc xml, poichè il certificato del clien non è disponibile
     * @param docxml
     * @return  
     */
    public int validaXml(Document  docxml){
           boolean validate;
            try {
            
            // Ho il certificato del client nel database? TODO: chiamare una funzione piu accurata
             
                  X509Certificate certClient = getCertificatoValido(XMLUtility.getValueStringInXML(docxml, "id"));
           
                // ho il certificato del client con cui posso validare
                System.out.println("Valido la richiesta utilizzando il certificato del client presente nel db");
              
                try {

                    validate = ValidateXMLSig.validateDigitalSignature(docxml,certClient.getPublicKey());

                    if(!validate){;
                        // 2 -> Verifica della firma fallita
                        System.out.println("Firma non valida");
                        return 0;

                    }else{
                        System.out.println("Firma valida");
                        return 1;
                    }
                } catch (Exception ex) {
                    System.out.println("C'è stato qualche errore nella verifica della firma");
                    return 0;
                }

            
        } catch (Exception ex) {
            try {
                // non ho il certificato del client. Ciò può succedere nelle prime interazioni,
                // quando io (CA) non l'ho ancora creato.
                System.out.println("VERIFICO LA FIRMA CON LA CHIAVE PRESENTE NELLA RICHIESTA XML");
                validate = ValidateXMLSig.validateDigitalSignature(docxml);
                
                if(!validate){;
                    
                    System.out.println("FIRMA NON VALIDA");
                    return 0;

                }else{
                    System.out.println("FIRMA OK");
                    return 2;
                }
                
            }
        
         catch (Exception ex1) {
                System.out.println("C'È STATO QUALCHE ERRORE NELLA VERIFICA DELLA FIRMA");
                return 0;
         } 
            }

        
    }


    /**
     * Funzione che recupera un certificato
     * @param docxml è il documento xml firmato
     * @return
     * @throws TransformerException 
     */
    public Document getCertByUsername(Document  docxml) throws TransformerException 
    {
        
       if(validaXml(docxml)!=0){
           System.out.println("Documento XML valido");
       }
                
        // Estraggo i parametri dal file
        String username = XMLUtility.getValueStringInXML(docxml, "id");        
        String tipo = XMLUtility.getValueStringInXML(docxml, "tipo");
        
        // Recupero il certificato
        String certificato_string = GestioneSQLite.getCertFirma(username, tipo);                
        System.out.println("CERTIFICATO RECUPERATO: "+certificato_string);

        // Creo il file xml che contiene i parametri: id e tipo. Il file xml mi serve per firmarlo nel digsign
        Document certificatoXML = XMLUtility.getDocumentCertificato(certificato_string);
        
        // Firmo il documento
        //richiestaStatusXML = XMLUtility.firmaDocumento(richiestaStatusXML, this.getPrivKey(), (PublicKey)this.pubKey);
        certificatoXML = XMLUtility.firmaDocumento(certificatoXML, this.getPrivKey(), this.getPubKey());            
            
        return certificatoXML;
    }
    
    /**
     * Rinnovo il certificato inviato dal client 
     * @param docxml
     * @return
     * 0 rinnovo fallito
     * 1 rinnovo con successo
     * 2 firma non valida
     */
    public Document rinnovoCertificato(Document  docxml)  
    {

        Document statusXML;
        int status = 0;
        String cognome = null;
        String nome = null;

        if(validaXml(docxml)!=0){
      
            System.out.println("\n------------------");       
            System.out.println("FIRMA DELLA RICHIESTA DI RINNOVO VALIDA");       

            // Estraggo i parametri dal file
            String pair = XMLUtility.getValueStringInXML(docxml, "pair");        
            nome = XMLUtility.getValueStringInXML(docxml, "nome");
            cognome = XMLUtility.getValueStringInXML(docxml, "cognome");
            String tipo = XMLUtility.getValueStringInXML(docxml, "tipo");                
            System.out.println("ESTRAGGO I PARAMETRI DEL FILE XML ARRIVATO (pair, nome, cognome, tipo) "+pair+" "+nome+" "+cognome+" "+tipo+")\n");                                       
            
            System.out.println("AGGIUNTO LA RICHIESTA DI CERTIFICATO DA APPROVARE");
            if(this.richiediRinnovoCertificato(tipo, pair, nome, cognome, Utility.RINNOVO_CERTIFICATO)) {
               status = 1;
            }
             else {
                status = 0;
            }
        }else{
            status = 2;
        }
                     
        // Creo il file xml che contiene i parametri: id e tipo. Il file xml mi serve per firmarlo nel digsign
        statusXML = XMLUtility.getDocumentStatus(Integer.toString(status));

        // Firmo il documento
        statusXML = XMLUtility.firmaDocumento(statusXML, this.getPrivKey(), this.getPubKey());  

        // utilità di interfaccia grafica
        last_call = Calendar.getInstance().getTime();   
        this.message_gui="E' stato richiesto il rinnovo per il certificato da parte di "+nome+" "+cognome;

        System.out.println("----------------\n");

        return statusXML;
    }   
    
   
    
    // Crea una CRL vuota (primo avvio)
    /**
     *
     */
    public void createCRL(){
        try {        
            X509V2CRLGenerator   crlGen = new X509V2CRLGenerator();
            Date                 now = new Date();
            Date                 nextUpdate = new Date(System.currentTimeMillis() + 120000); // un giorno
            X509Certificate      caCrlCert = caCert;
            PrivateKey           caCrlPrivateKey = (PrivateKey) getPrivKey();
           
            
            crlGen.setIssuerDN(new X500Principal("CN=Test CA"));

            crlGen.setThisUpdate(now);
            crlGen.setNextUpdate(nextUpdate);
            crlGen.setSignatureAlgorithm("SHA1withRSA");

            //crlGen.addCRLEntry(BigInteger.ONE, now, CRLReason.privilegeWithdrawn);

            // aggiungo, alla CRL che sto creando, la CRL attuale (nel caso la stia solo rinnovando)
            //crlGen.addCRL(Crl);
            
            crlGen.addExtension(X509Extensions.AuthorityKeyIdentifier, 
                              false, new AuthorityKeyIdentifierStructure(caCert));
            crlGen.addExtension(X509Extensions.CRLNumber, 
                              false, new CRLNumber(BigInteger.valueOf(1)));

            // ho creato una CRL vuota, ora la popolo leggendo dal database
            Vector<Certificato> certificatiRevocati = GestioneSQLite.retriveCertificatiRevocati();
            
            if (certificatiRevocati != null) {
                for (int i = 0; i < certificatiRevocati.size(); i++) {
                    
                    /* TODO: La data di revoca del certificato da db
                     * String revoca = cert.get(i).getDataRevoca();
                    System.out.println(revoca);
                    DateFormat formatter;
                    Date date;
                    formatter = new SimpleDateFormat("dd-MMM-yyyy-HH:mm");
                    date = (Date) formatter.parse(revoca);
                    */
                    
                    // creo il certificato revocato
                    byte[] val_byte = Base64.decode(certificatiRevocati.get(i).getCertificato());
                javax.security.cert.X509Certificate x509 = null;
                try {
                    x509 = javax.security.cert.X509Certificate.getInstance(val_byte);
                    //x509 = javax.security.cert.X509Certificate.getInstance(val.getBytes());
                } catch (javax.security.cert.CertificateException ex) {
                    Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
                }
                
                    crlGen.addCRLEntry(x509.getSerialNumber(), new Date(), CRLReason.privilegeWithdrawn);
                }
            }
            
            // genero la CRL
            X509CRL    crl = crlGen.generateX509CRL(caCrlPrivateKey, "BC");
            
    
            Crl = crl;
            
    /*        // CRL caricata, ora la salvo nel database
            byte[] crlCoded = Base64.encode(crl.getEncoded());
            String strCrlCoded = new String(crlCoded);
            GestioneSQLite.inserisciCrl(strCrlCoded);
    */
            System.out.println("CRL creata");
        } catch (NoSuchProviderException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SignatureException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvalidKeyException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } catch (CertificateParsingException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        }
                        	
    }
    
    /*
     * Inserisco un certificato revocato alla CRL
     * 1) Creo un nuovo generatore di CRL dalla vecchia CRL
     * 2) Aggiungo il certificato alla nuova CRL
     * 3) La salvo nel database
     */
    /**
     *
     * @param SerialNumber
     * @return
     * @throws Exception
     */
    public boolean insertInCrl(BigInteger SerialNumber) throws Exception{
    	X509V2CRLGenerator   crlGen = new X509V2CRLGenerator();
    	X509CRL              existingCRL = Crl; // devo caricare quella vecchia
    	crlGen.setIssuerDN(new X500Principal("CN=Test CA"));

    	crlGen.setThisUpdate(new Date());
    	crlGen.setNextUpdate(new Date(System.currentTimeMillis() + 60000*60*60*24));
    	crlGen.setSignatureAlgorithm("SHA1withRSA"); // non so il sigAlg migliore
    	crlGen.addCRL(existingCRL);

    	// impostare il numero del certificato da inserire
    	crlGen.addCRLEntry(SerialNumber, new Date(), CRLReason.privilegeWithdrawn);

    	crlGen.addExtension(X509Extensions.AuthorityKeyIdentifier, 
    	                  false, new AuthorityKeyIdentifierStructure(caCert));
    	crlGen.addExtension(X509Extensions.CRLNumber, 
    	                  false, new CRLNumber(BigInteger.valueOf(1)));

    	X509CRL    crl = crlGen.generateX509CRL((PrivateKey) getPrivKey(), "BC");
    	
    	Crl = crl;
        
        // Converto la CRL in bytestream per salvarla nel database
        byte[] crlCoded = Base64.encode(crl.getEncoded());
        String strCrlCoded = new String(crlCoded);
        
        return GestioneSQLite.inserisciCrl(strCrlCoded);
        
        //System.out.println("Certificato inserito nella crl");
    }
    
   /*
    * Legge la crl da db e la mette nella variabile Crl. DA RIMUOVERE??
    */
    /**
     *
     * @throws CRLException
     * @throws CertificateException
     */
    public void caricaCrl() throws CRLException, CertificateException{
     
       // recupero la crl codificata dal database e la converto in oggetto CRL
       String crlCoded=GestioneSQLite.leggiCrl();
        byte[] decoded = Base64.decode(crlCoded);           
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream is = new ByteArrayInputStream(decoded);
        Crl = (X509CRL)cf.generateCRL(is);
   }
    
   /**
    * Funzione chiamata dalla GUI per revocare il certificato selezionato
    * @param id
    * @param tipo
    * @return 
    */
   public boolean revocaCertificato(String id, String tipo){
    try {
        // Revoco il certificato
        boolean status = GestioneSQLite.revocaCertificato(id,tipo);

        // utilità di interfaccia grafica
        last_call = Calendar.getInstance().getTime();  
        this.message_gui = "Certificato di "+id+" revocato";

        return status;

       } catch (Exception ex) {
           Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
           return false;
       }
   }
   
   /** TODO: deve ricevere id e tipo
    * Funzione chiamata dal client per la revoca di un certificato
    * @param docxml 
    * @return un documento xml con l'esito dell'operazione
    * 0 se revoca fallita    
    * 1 se ok
    * 2 se firma non valida
    * 3 errore nella verifica della firma    
    * 4 qualche errore nel database
    */
   public Document revocaCertificato(Document docxml){
       String id="";
        System.out.println("\n---------------\n"
            + "REVOCA UN CERTIFICATO");    
        //esito della revoca
        int status_integer = 0;

        try {
         // estraggo dall'xml i dati dell'utente per andare ad estrarre il certificato
         // da database e leggerne la chiave pubblica per poi validare l'xml

         if(validaXml(docxml) == 0){
             // 2 -> Verifica della firma fallita
             System.out.println("VERIFICA FALLITA NELLA FIRMA");
             status_integer = 3;

         }else{
            System.out.println("VERIFICA FIRMA OK");
            id = XMLUtility.getValueStringInXML(docxml, "id");        
            String tipo = XMLUtility.getValueStringInXML(docxml, "tipo");      
            try {
              // Revoco il certificato
              if(GestioneSQLite.revocaCertificato(id,tipo)){
                  status_integer = 1;
              }else{
                  status_integer = 0;
              }
            } catch (Exception ex) {
                //Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
                status_integer = 4;
            }                     
         }
        } catch (Exception ex) {
         System.out.println("QUALCHE ERRORE NELLA VERIFICA DELLA FIRMA");
         status_integer = 3;
        }

        // Creo il documento con la risposta
        Document status_doc = XMLUtility.getDocumentRispostaInt(status_integer);

        System.out.println("FIRMO XML CON STATUS");
        // Firmo il documento
        Document status_doc_sign = XMLUtility.firmaDocumento(status_doc, privKey, pubKey);

        // utilità di interfaccia grafica
        last_call = Calendar.getInstance().getTime();  
        this.message_gui="Richiesta di revoca da parte di "+id;

        System.out.println("FINE REVOCA DEL CERTIFICATO "+status_integer
             + "\n-------------------");
        return status_doc_sign;           
   }
   
   /**
    * Funzione chiamata dal client per ottenere la CRL
    * @return un documento xmldigsig con la CRL
    */
   public Document retrieveCRL(){
        System.out.println("Un client richiede la Crl");

       // se la CRL in memoria è scaduta, la ricreo da database
       Date scadenzaCrl = Crl.getNextUpdate();
        if (new Date().after(scadenzaCrl) || politica==Utility.POLITICA_CRL_RIGENERAZIONE_OGNI_RICHIESTA) {
            System.out.println("La Crl è scaduta: la rigenero");
            createCRL();
        }
       
       // Creo il documento con la risposta TODO
                            
        Document status_doc = XMLUtility.getDocumentRispostaCrl(Crl);
        // Firmo il documento
        Document status_doc_sign = XMLUtility.firmaDocumento(status_doc, privKey, pubKey);

        return status_doc_sign;
             
   }
   
    // Controlla se un certificato è revocato tramite richiesta OCSP al server
    /**
     *
     * @param cert
     */
    public void controllaOcsp(X509Certificate cert){
    	TigerOcsp.validate(caCert, cert);
    } 
    
    /**
     * Ritorna 
     *  1 se un certificato è revocato
     *  0 se è valido
     *  2 se firma non valida
     *  3 se c'è stato un errore
     * @param docxml 
     * @return 
     */
    public Document getControlloOCSP(Document  docxml){
        
        String status = "0";
        System.out.println("\nRICEVO RICHIESTA OCSP DAL CLIENT... ");
        System.out.println("CONTROLLO VALIDAZIONE RICHIESTA DEL CLIENT... ");

        try {
            
            if(validaXml(docxml)==0){;
                // 2 -> Verifica della firma fallita
                System.out.println("...FIRMA NON VALIDA ");
                status= "2";                
            }else{
                System.out.println("... VERIFICA FIRMA ESEGUITA CON SUCCESSO");
                
                // Estraggo i parametri dal file
                String certificato = XMLUtility.getValueStringInXML(docxml, "certificato");
                
                // Creo il certificato dalla stringa
                X509Certificate certificatoX509 = Utility.creaCertificatoDaStringa(certificato);                
                
                // Estraggo il serial
                BigInteger serialNumber = certificatoX509.getSerialNumber();
                
                // Richiesta di validtà al DB
                System.out.println("... IL SERIAL NUMBER DEL CERTIFICATO DA CERCARE È: "+serialNumber.toString());
                int certificato_valido = GestioneSQLite.certificatoRevocato(serialNumber.toString());
                 
                // Valido o non valido
                if(certificato_valido==0){
                    status = "0";
                    System.out.println("... IL CERTIFICATO NON È PIU' VALIDO");

                }else{
                    status = "1";
                    System.out.println("... IL CERTIFICATO È VALIDO");                    
                }
            }
        } catch (Exception ex) {
            System.out.println("... ERRORE NELLA VERIFICA DELLA FIRMA");
            status = "3";
        }
          
        // Creo il file xml che contiene i parametri: status. Il file xml mi serve per firmarlo nel digsign
        Document rispostaXML = XMLUtility.getDocumentRispostaInt(Integer.parseInt(status));
       
        // Firmo il documento
        //richiestaStatusXML = XMLUtility.firmaDocumento(richiestaStatusXML, this.getPrivKey(), (PublicKey)this.pubKey);
        rispostaXML = XMLUtility.firmaDocumento(rispostaXML, this.getPrivKey(), this.getPubKey());            
                    
        System.out.println("... RITORNO AL CLIENT LA RISPOSTA OCSP\n");
        return rispostaXML;
    }

    /**
     * Ritorna il certificato di username, SE È VALIDO (scadenza e non revocato)
     * @param username
     * @return
     * @throws ExceptionCertificatoNonCreato
     * @throws ExceptionCertificatoNonValido  
     */
    public  X509Certificate getCertificatoValido(String username) throws ExceptionCertificatoNonCreato, ExceptionCertificatoNonValido{
        String certificato_string = GestioneSQLite.getCertFirmaValido(username);
        X509Certificate certificato = Utility.creaCertificatoDaStringa(certificato_string);
        return certificato;
    }
    
    /**
     * Utilità per l'aggiornamento della GUI 
     * @return 
     */
    public Date getLastCall(){
        return last_call;
    }
    
    
    /**
     * Utilità per l'aggiornamento della GUI 
     * @return 
     */
    public String getMessage(){
        return message_gui;
    }    
    
    /**
     * Legge il certificato da database
     */
    private void readCert() throws IOException{
        
        System.out.println("\n-----------------");
        System.out.println("RECUPERO CERTIFICATO DI Central Authority Central Authority");
        String certStringa = GestioneSQLite.getCertFirma("Central Authority Central Authority", "0");
        System.out.println("CERTIFICATO RECUPERATO");
        
        try {
            caCert = Utility.creaCertificatoDaStringa(certStringa);
        } catch (ExceptionCertificatoNonCreato ex) {
            System.err.println("Errore in readCert() sull'invocazione di Utility.creaCertificatoDaStringa");
        }
        System.out.println("-----------------\n");
    }
            
    /*
     * Legge le chiavi da db e le salva nell'oggetto
     */
    private void readKey() throws NoSuchAlgorithmException, IOException{
        // recupero chiavi
        String[] chiavi=GestioneSQLite.leggiChiavi("Central Authority","Central Authority");
       
        KeyPair kpProv = null;
        
        // chiave pubblica
        PEMReader readKP = new PEMReader(new StringReader(chiavi[1]));
        pubKey = (PublicKey) readKP.readObject();
        
        // chiave privata
        readKP = new PEMReader(new StringReader(chiavi[0]), new PasswordFinder() {
                        public char[] getPassword() {
                             return password.toCharArray();
                              }
                                });

        kpProv = (KeyPair) readKP.readObject();		
        privKey = kpProv.getPrivate();
        
        // KeyPair della classe
        kp = new KeyPair((PublicKey)pubKey,(PrivateKey) privKey);
                 
        System.out.print("CARICATA LA CHIAVE PUBBLICA " );
        System.out.println("E LA CHIAVE PRIVATA");
    }
    
    private Key getPubKey(){
            return pubKey;
    }

    private Key getPrivKey(){
            return privKey;
    }
    
    /**
     *
     * @param docxml
     * @return
     * @throws IOException
     */
    public Document verificaOCSP(Document docxml) throws IOException{
         try {
            System.out.println("Client richiede OCSP");
            
            String richiestaOCSP = XMLUtility.getValueStringInXML(docxml, "certificato");
                
            OCSPReq req = new OCSPReq(Base64.decode(richiestaOCSP.getBytes()));
            
            BasicOCSPRespGenerator basicRespGen = new BasicOCSPRespGenerator(caCert.getPublicKey());
            Req[] requests = req.getRequestList();
            CertificateID certID = requests[0].getCertID();
            
            // Controllo la scadenza della CRL e la rigenero in caso
            Date scadenzaCrl = Crl.getNextUpdate();
            if (new Date().after(scadenzaCrl) || politica==Utility.POLITICA_CRL_RIGENERAZIONE_OGNI_RICHIESTA) {
                System.out.println("La Crl è scaduta: la rigenero");
                createCRL();
            }
            
            X509CRLEntry entry = Crl.getRevokedCertificate(certID.getSerialNumber());
            if (entry != null) {
                basicRespGen.addResponse(certID, new RevokedStatus(entry.getRevocationDate(), CRLReason.privilegeWithdrawn));
                System.out.println("Certificato revocato");
            } else {
                basicRespGen.addResponse(certID, CertificateStatus.GOOD);
                System.out.println("Certificato non revocato");
            }

            BasicOCSPResp basicResp = null;
            try {
                basicResp = basicRespGen.generate("SHA256WithRSA",
                        (PrivateKey)getPrivKey(), null, new Date(), "BC");
            } catch (Exception e) {
                System.out.println("Impossibile generare la risposta OCSP, impossibile continuare");
                
            }
            OCSPRespGenerator respGen = new OCSPRespGenerator();
             
             
             Document rispostaXML = XMLUtility.getDocumentRispostaOCSP(respGen.generate(OCSPRespGenerator.SUCCESSFUL, basicResp));
       
        // Firmo il documento
        //richiestaStatusXML = XMLUtility.firmaDocumento(richiestaStatusXML, this.getPrivKey(), (PublicKey)this.pubKey);
        rispostaXML = XMLUtility.firmaDocumento(rispostaXML, this.getPrivKey(), this.getPubKey());            
        
        return rispostaXML;
        
           
        } catch (OCSPException ex) {
            Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        } 
        return null;
    }

    /**
     * Inizializzazione CA
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     * @throws CertificateEncodingException
     * @throws IllegalStateException
     * @throws SignatureException
     * @throws InvalidKeyException
     * @throws IOException
     * @throws ExceptionProfiloGiaPresente
     * @throws ExceptionCertificatoGiaPresente
     * @throws KeyStoreException
     * @throws CertificateException 
     */
    private void creaCertificatoCA() throws NoSuchAlgorithmException, NoSuchProviderException, CertificateEncodingException, IllegalStateException, SignatureException, InvalidKeyException, IOException, ExceptionProfiloGiaPresente, ExceptionCertificatoGiaPresente, KeyStoreException, CertificateException {
        //Generazione e salvataggio delle chiavi
        Security.addProvider(new BouncyCastleProvider());
        KeyPairGenerator generator;
        generator = KeyPairGenerator.getInstance("RSA", "BC");
        //generator.initialize(4096);
        generator.initialize(1024); //per tempo
        kp = generator.generateKeyPair();
        pubKey = kp.getPublic();
        privKey = kp.getPrivate();
        //char[] pass = password.toCharArray(); 
        System.out.println("Generate chiavi CA");

        /*
        * Creo certificato della CA
        * Il certificato deve contenere:
        * - DN
        * - Tempo di validità
        * - Serial Number (corrispondente all'ora in cui viene creato)
        * -
        */
        // Definisco i valori del DN: CN + O + OU + C
        String CN = "Central Authority";
        String O = "Math.Unipd";
        String OU = "Informatica";
        String C = "Italy";
        String email = "info_central_autority@math.unipd.it";


        // Data di creazione
        Calendar ora = Calendar.getInstance();
        Date now = ora.getTime();

        // Data di scadenza 5 anni dalla creazione
        int year_futuro = ora.get(Calendar.YEAR)+5;                
        Calendar calendar_futuro = ora.getInstance();               
        calendar_futuro.set(Calendar.YEAR, (year_futuro));
        Date data_futuro = calendar_futuro.getTime();  

        System.out.println("Creato il:\t"+ora.getTime());
        System.out.println("Scade il:\t"+calendar_futuro.getTime());

        // Serial number
        BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());

        // Coppia di chiavi pubblica e privata (ci interessa la pubblica)
        KeyPair keyPair = kp;

        // Costruisco il certificato autofirmato
        X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
        X500Principal subjectName = new X500Principal("CN=" + CN + ", O=" + O + ", OU=" + OU + ", C=" + C);
        certGen.setSerialNumber(serialNumber);
        certGen.setIssuerDN(new X500Principal("CN=" + CN + ", O=" + O + ", OU=" + OU + ", C=" + C));
        certGen.setNotBefore(now);
        certGen.setNotAfter(data_futuro);
        certGen.setSubjectDN(subjectName);
        certGen.setPublicKey(keyPair.getPublic());
        // Definisce l'algoritmo che sarà usato per la creazione del digest
        certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");
        //certGen.addExtension(X509Extensions.AuthorityKeyIdentifier, false,new AuthorityKeyIdentifierStructure(rootCert));
        certGen.addExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.dataEncipherment | KeyUsage.cRLSign));

        java.security.cert.X509Certificate cert = certGen.generate(privKey, "BC");

        System.out.println("CREATO IL CERTIFICATO DELLA CA");                

        /*
        * Converto il certificato in Stringa, per inserirlo nel db
        * 
        */          
        String strCertCoded = Utility.creaStringaDaCertificato(cert);

        byte[] val_byte = Base64.decode(strCertCoded);
        javax.security.cert.X509Certificate x509 = null;

        try {
        x509 = javax.security.cert.X509Certificate.getInstance(val_byte);
        //x509 = javax.security.cert.X509Certificate.getInstance(val.getBytes());
        } catch (javax.security.cert.CertificateException ex) {
        Logger.getLogger(Ca.class.getName()).log(Level.SEVERE, null, ex);
        }

        X509Certificate certificatoX509 = Utility.convert(x509);

        // salvo il certificato nell'attributo della CA
        caCert = cert;                                                

        /*
        * Salvo il certificato su file per i client 
        */                

        FileWriter cf;
        cf = new FileWriter("ca/cert/my.cert");
        PEMWriter pemWriterFile = new PEMWriter(cf);
        pemWriterFile.writeObject(certificatoX509);
        pemWriterFile.flush();
        pemWriterFile.close();

        /*
        * Salvo il certificato nel database
        */
        String from = Utility.convertDateToString(now);
        String until = Utility.convertDateToString(data_futuro);
        // creo profilo della CA nel db
        GestioneSQLite.inserisciProfilo(CN, CN, O, OU, C, email);
        //scrivo su DB le chiavi della CA
        GestioneSQLite.insertChiavi("Central Authority","Central Authority", privKey, pubKey, password.toCharArray());
        //inserisco il cert della CA nella tabella dei certificati attivi
        GestioneSQLite.inserisciCertFirma(Utility.creaStringaDaCertificato(cert), "Central Authority Central Authority", "0",cert.getSerialNumber().toString() ,from, until);

        //--------------------------------------------------------------------------------------------
        // costruisco il KeyStore ?????
        ks = KeyStore.getInstance("JKS");
        ks.load( null, null );  

        // get user password and file input stream
        char[] passwordc = password.toCharArray();
        File keystoreFile = new File("ca/my.keystore");

        String alias = "myalias";
        // Add the certificate
        ks.setCertificateEntry(alias, cert);
        // Save the new keystore contents
        FileOutputStream out = new FileOutputStream(keystoreFile);
        ks.store(out, passwordc);
        out.close();

        //-------------------------
        // Load the keystore in the user's home directory
        FileInputStream is = new FileInputStream("ca/my.keystore");

        KeyStore keystore = KeyStore.getInstance("JKS");
        keystore.load(is, passwordc);

        // Get certificate
        java.security.cert.X509Certificate certr = (X509Certificate) keystore.getCertificate("myalias");
        //---------------------------------------------------------------------------


        this.readCert();

        // inizializzo la lista CRL per i certificati revocati
        System.out.println("AVVIO LA CREAZIONE DELLA CRL");                
        this.createCRL();
        System.out.println("CRL CREATA");
    }
        
}
